﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Wizard Buttons Control Class
 *      Provides a common control mechanism for displaying and using the typical
 * wizard-style buttons.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using Adaptive.Foundation;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides a common control mechanism for displaying and using the typical
    /// wizard-style buttons.
    /// </summary>
    [Browsable(true), ToolboxItem(true), DesignerCategory("UserControl"),
    System.ComponentModel.Designer(typeof(System.Windows.Forms.Design.ParentControlDesigner))]
    public partial class WizardButtonsControl : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when the cancel button is clicked.
        /// </summary>
        public event EventHandler CancelClick;
        /// <summary>
        /// OCcurs when the Back button is clicked.
        /// </summary>
        public event EventHandler BackClick;
        /// <summary>
        /// Occurs when the Next button is clicked.
        /// </summary>
        public event EventHandler NextClick;
        /// <summary>
        /// Occurs when the Finish button is clicked.
        /// </summary>
        public event EventHandler FinishClick;
        /// <summary>
        /// Occurs when the page count property is modified.
        /// </summary>
        public event EventHandler PageCountChanged;
        /// <summary>
        /// Occurs when the current page property is modified.
        /// </summary>
        public event EventHandler CurrentPageChanged;
        /// <summary>
        /// Occurs just before a button click event is raised to validate current form content.
        /// </summary>
        public event CancelEventHandler PreValidateContent;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations

        /// <summary>
        /// 
        /// </summary>
        private const int DEFAULT_BUTTON_MARGIN = 4;
        /// <summary>
        /// 
        /// </summary>
        private const int DEFAULT_BUTTON_WIDTH = 81;
        /// <summary>
        /// 
        /// </summary>
        private const int DEFAULT_BUTTON_HEIGHT = 25;

        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations

        /// <summary>
        /// 
        /// </summary>
        private int _buttonMargin = DEFAULT_BUTTON_MARGIN;
        private int _buttonWidth = DEFAULT_BUTTON_WIDTH;
        private int _buttonHeight = DEFAULT_BUTTON_HEIGHT;
        private int _pageCount;
        private int _currentPage = -1;

        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public WizardButtonsControl()
            : base()
        {
            InitializeComponent();
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the width of the buttons, in pixels.
        /// </summary>
        /// <value>
        /// The width of each button, in pixels.
        /// </value>
        [Browsable(true), DefaultValue(DEFAULT_BUTTON_WIDTH), Description("The width of each button, in pixels.")]
        public int ButtonWidth
        {
            get { return _buttonWidth; }
            set
            {
                _buttonWidth = value;
                InitializeContent();
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the height of the buttons, in pixels.
        /// </summary>
        /// <value>
        /// The height of each button, in pixels.
        /// </value>
        [Browsable(true), DefaultValue(DEFAULT_BUTTON_HEIGHT), Description("The height of each button, in pixels.")]
        public int ButtonHeight
        {
            get { return _buttonHeight; }
            set
            {
                _buttonHeight = value;
                InitializeContent();
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the size of the space surrouding the buttons.
        /// </summary>
        /// <value>
        /// The padding around each button, in pixels.
        /// </value>
        [Browsable(true), DefaultValue(DEFAULT_BUTTON_MARGIN), Description("The padding around each button, in pixels.")]
        public int ButtonMargin
        {
            get { return _buttonMargin; }
            set
            {
                _buttonMargin = value;
                InitializeContent();
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the number of "pages" in the wizard.
        /// </summary>
        /// <value>
        /// The number of steps in the wizard dialog.
        /// </value>
        [Browsable(true), DefaultValue(0), Description("The number of steps in the dialog.")]
        public int PageCount
        {
            get { return _pageCount; }
            set
            {
                if (_pageCount != value)
                {
                    _pageCount = value;
                    UpdateCurrentControlContents();
                    Invalidate();
                    OnPageCountChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// Gets or sets the current step or page number in the wizard dialog.
        /// </summary>
        /// <remarks>
        /// This is used to determine when the last step is reached and the "Finish" button
        /// may be used; also when the first page is reached and the Back button must be disabled.
        /// </remarks>
        /// <value>
        /// The ordinal index of the current position, using zero (0) as the first item, or 
        /// -1 if not set.
        /// </value>
        [Browsable(true), DefaultValue(0), Description("The current page number value.")]
        public int CurrentPage
        {
            get { return _currentPage; }
            set
            {
                if (_currentPage != value)
                {
                    _currentPage = value;
                    UpdateCurrentControlContents();
                    Invalidate();
                    OnCurrentPageChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// Gets the height of the control.
        /// </summary>
        /// <value>The height of the control in pixels.</value>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/>
        /// 	<IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// </PermissionSet>
        public new int Height
        {
            get
            {
                base.Height = _buttonMargin * 2 + _buttonHeight + 4;
                return base.Height;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Raises the <see cref="CancelClick"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnCancelClick(EventArgs e)
        {
            if (CancelClick != null)
                CancelClick(this, e);
        }
        /// <summary>
        /// Raises the <see cref="BackClick"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnBackClick(EventArgs e)
        {
            if (BackClick != null)
                BackClick(this, e);
        }
        /// <summary>
        /// Raises the <see cref="NextClick"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnNextClick(EventArgs e)
        {
            if (NextClick != null)
                NextClick(this, e);
        }
        /// <summary>
        /// Raises the <see cref="FinishClick"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnFinishClick(EventArgs e)
        {
            if (FinishClick != null)
                FinishClick(this, e);
        }
        /// <summary>
        /// Raises the <see cref="PageCountChanged"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnPageCountChanged(EventArgs e)
        {
            if (PageCountChanged != null)
                PageCountChanged(this, e);
        }
        /// <summary>
        /// Raises the <see cref="CurrentPageChanged"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnCurrentPageChanged(EventArgs e)
        {
            if (CurrentPageChanged != null)
                CurrentPageChanged(this, e);
        }
        /// <summary>
        /// Raises the <see cref="PreValidateContent"/> event.
        /// </summary>
        /// <param name="e">
        /// A <see cref="CancelEventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnPreValidateContent(CancelEventArgs e)
        {
            if (PreValidateContent != null)
                PreValidateContent(this, e);
        }
        /// <summary>
        /// Creates and assigns the event handlers for the items contained within the control.
        /// </summary>
        protected override void AssignEventHandlers()
        {
            BackButton.Click +=new EventHandler(HandleBackButtonClick);
            NextFinishButton.Click +=new EventHandler(HandleNextFinishClick);
            CloseButton.Click +=new EventHandler(HandleCloseClick);
        }
        /// <summary>
        /// Removes the event handlers for the items contained within the control.
        /// </summary>
        protected override void RemoveEventHandlers()
        {
            BackButton.Click -= new EventHandler(HandleBackButtonClick);
            NextFinishButton.Click -= new EventHandler(HandleNextFinishClick);
            CloseButton.Click -= new EventHandler(HandleCloseClick);
        }
        /// <summary>
        /// Initializes the content of the control before the event handlers are assigned.
        /// </summary>
        protected override void InitializeContent()
        {
            Size buttonSize;
            Point buttonLocation;
            Size panelSize;

            buttonSize = new Size(_buttonWidth, _buttonHeight);
            buttonLocation = new Point(_buttonMargin, _buttonMargin);
            panelSize = new Size(_buttonWidth + _buttonMargin * 2, _buttonHeight + _buttonMargin * 2);

            BackButton.Size = buttonSize;
            BackButton.Location = buttonLocation;

            NextFinishButton.Size = buttonSize;
            NextFinishButton.Location = buttonLocation;

            CloseButton.Size = buttonSize;
            CloseButton.Location = buttonLocation;

            BackPanel.Size = panelSize;
            NextFinishPanel.Size = panelSize;
            ClosePanel.Size = panelSize;
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl()"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        protected override void UpdateCurrentControlContents()
        {
            if ((_pageCount < 1) || (_currentPage <= -1))
            {
                NextFinishButton.Visible = false;
                BackButton.Visible = false;
            }
            else
            {
                if (_currentPage == _pageCount - 1)
                {
                    BackButton.Enabled = true;
                    NextFinishButton.Text = "Fi&nish";
                    NextFinishButton.Enabled = true;
                }
                else
                {
                    NextFinishButton.Enabled = true;
                    BackButton.Enabled = (_currentPage > 0);
                    NextFinishButton.Text = "&Next >>";
                }
                NextFinishButton.Visible = true;
                BackButton.Visible = true;
            }
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl(object[])"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        /// <param name="data">
        /// The data supplied to the control to update the internal controls with.
        /// </param>
        protected override void UpdateCurrentControlContents(object[] data)
        {
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        /// <summary>
        /// Handles the event when the Back button is clicked.
        /// </summary>
        /// <param name="sender">
        /// The object raising the event.
        /// </param>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        private void HandleBackButtonClick(object sender, EventArgs e)
        {
            OnBackClick(e);
        }
        /// <summary>
        /// Handles the event when the Back button is clicked.
        /// </summary>
        /// <param name="sender">
        /// The object raising the event.
        /// </param>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        private void HandleNextFinishClick(object sender, EventArgs e)
        {
            CancelEventArgs evArgs = null;

            evArgs = new CancelEventArgs();
            evArgs.Cancel = false;
            OnPreValidateContent(evArgs);
            if (!evArgs.Cancel)
            {
                if (_currentPage == _pageCount - 1)
                    OnFinishClick(e);
                else
                    OnNextClick(e);
            }
        }

        /// <summary>
        /// Handles the event when the Back button is clicked.
        /// </summary>
        /// <param name="sender">
        /// The object raising the event.
        /// </param>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        private void HandleCloseClick(object sender, EventArgs e)
        {
            OnCancelClick(e);
        }
        #endregion
    }
}
